/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#pragma once
#include <list>
#include <memory>
#include <mutex>
#include <string>

#include "framework/common.h"
#include "framework/list.h"
#include "framework/msg.h"
#include "framework/worker.h"

#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)

#define RESOLUTION_MS 10

namespace air {
namespace link {

class Timer : public Node {
  friend class TimerManager;

 public:
  Timer() {}
  virtual ~Timer() {}

  std::string actor_name_;
  std::string timer_name_;
  uint32_t m_expire_;  // interval
  bool m_run_;
};

class TimerManager {
 public:
  TimerManager();
  virtual ~TimerManager();

  int Timeout(const std::string& actor_name, const std::string& timer_name,
              int time);

  std::list<std::shared_ptr<Msg>>& Updatetime();

 private:
  void AddTimerNode(Timer* node);
  void Updatetimer();
  void Execute();
  void MoveList(int level, int idx);
  void Shift();
  void Dispath(List* cur);

  List tv1_[TVR_SIZE];
  List tv2_[TVN_SIZE];
  List tv3_[TVN_SIZE];
  List tv4_[TVN_SIZE];
  List tv5_[TVN_SIZE];
  List* tv_[4];

  uint32_t time_;
  uint64_t cur_point_;

  std::list<std::shared_ptr<Msg>> timeout_list_;
  std::mutex mutex_;
};

class WorkerTimer : public Worker {
  friend class App;

 public:
  WorkerTimer();
  virtual ~WorkerTimer();

  int SetTimeout(const std::string& actor_name, const std::string& timer_name,
                 int time);

  /**
   * override Worker virtual method
   */
  void Run() override;
  void OnInit() override;
  void OnExit() override;

  /**
   * override Event virtual method
   */
  EventType GetEventType() override { return EventType::WORKER_TIMER; }

 private:
  int Work();

  TimerManager timer_mgr_;
};

}  // namespace link
}  // namespace air
